/*
 *  Copyright (C) 2008 Nuke (wiinuke@gmail.com)
 *
 *  this file is part of GeckoOS for USB Gecko
 *  http://www.usbgecko.com
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

 // very old 2007 wii dvd functions

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
#include <malloc.h>
#include "font.h"
#include "ogc/ipc.h"
#include "geckodvd.h"
#include "geckomenu.h"
#include "dvd_broadway.h"
#include "tools.h"

#define DI_INSIZE			0x20	// if less then 0x20 it seems to fail
#define READ_DVD			0xD0

#define Inquiry				0x12
#define READ_ID				0x70
#define Low_read			0x71
#define Wait_cover_close	0x79
#define Get_cover_reg		0x7A
#define Notify_reset		0x7E
#define Read_dvd_physical	0x80
#define Read_dvd_copyright	0x81
#define Read_dvd_key		0x82
#define Clear_cover_int		0x86
#define Get_cover_status	0x88
#define RESET_DRIVE			0x8A
#define Open_partition		0x8B
#define Close_partition		0x8C
#define READ_UNC			0x8D
#define READ_DVD			0xD0
#define OPEN_PART			0x8B
#define ENABLE_DVD			0x8E
#define STOP_MOTOR			0xE3
#define STOP_LASER			0xD2


#define dvdpacketsize 61440
#define sectorsize 2048
#define dbbuffchecksize 61444 // 2048 * 30 sectors + checksum

static vu32 dvddone = 0;
s32 dvdhandle;
int dvdopen = 0;

u32 *bufferin;
u32 *bufferout;

static void __dvd_readidcb(s32 result)
{
	dvddone = result;
}


/*---------------------------------------------------------------------------*
    Name:               dvd_openios()
    Description:        Open the Drive interface on the IOS
*---------------------------------------------------------------------------*/
s32 dvd_openios()
{
	static char dev_di[] ATTRIBUTE_ALIGN(32) = "/dev/di";
	
	dvdhandle = IOS_Open(dev_di, 0);
	if(dvdhandle < 0){
		return dvdhandle;
	}

	bufferin = (u32 *) allocate_memory( DI_INSIZE);	
	bufferout = (u32 *) allocate_memory( DI_INSIZE);
	dvdopen = 1;
	return 1;
}

/*---------------------------------------------------------------------------*
    Name:               dvd_closeios()
    Description:        Close the IOS dvdhandle
*---------------------------------------------------------------------------*/
u32 dvd_closeios()
{
	if(dvdopen){
		IOS_Close(dvdhandle);
		dvdopen = 0;
		free(bufferin);
		free(bufferout);
		return 1;
	}
	return 0;
}

/*---------------------------------------------------------------------------*
    Name:               dvd_stopdrive
    Description:        Stop Drive
*---------------------------------------------------------------------------*/
s32 dvd_stoplaser()
{
	s32 errorcode;
	
	if(!dvdopen){
		return -1;
	}

	bufferin[0] = STOP_LASER<<24;

	errorcode = IOS_Ioctl(dvdhandle,STOP_LASER,bufferin,0x20,bufferout,0x20);
	if(errorcode < 0){
		return errorcode;
	}
	return 1;
}


/*---------------------------------------------------------------------------*
    Name:               dvd_stopdrive
    Description:        Stop Drive
*---------------------------------------------------------------------------*/
s32 dvd_stopdrive()
{
	static u32 di_regbufferin[0x08] ATTRIBUTE_ALIGN(32);
	static u32 di_regbufferout[0x08] ATTRIBUTE_ALIGN(32);

	s32 errorcode;
	
//	if(!dvdopen){
//		return -1;
//	}

	di_regbufferin[0] = STOP_MOTOR<<24;

	errorcode = IOS_Ioctl(dvdhandle,STOP_MOTOR,di_regbufferin,0x20,di_regbufferout,0x20);
	if(errorcode < 0){
		return errorcode;
	}
	return 1;
}

/*---------------------------------------------------------------------------*
    Name:               dvd_reset
    Description:        Reset Drive
*---------------------------------------------------------------------------*/
s32 dvd_reset()
{

	s32 errorcode;
	
	if(!dvdopen){
		return -1;
	}
	
	bufferin[0] = RESET_DRIVE<<24;

	errorcode = IOS_Ioctl(dvdhandle,RESET_DRIVE,bufferin,0x20,bufferout,0);
	if(errorcode < 0){
		return errorcode;
	}

	return 1;
}

/*---------------------------------------------------------------------------*
    Name:               dvd_Inquiry
    Description:        Reset Drive
*---------------------------------------------------------------------------*/
s32 dvd_inquiry()
{
	u32 *bufferin;
	u32 *bufferout;
	s32 errorcode;
	int i;

	if(!dvdopen){
		return -1;
	}
	
	bufferin = (u32 *) allocate_memory( 8);	
	bufferout = (u32 *) allocate_memory( 0x20);	
	
	memset(bufferout, 0, 0x20);

	bufferin[0] = 0x12<<24;
	bufferin[1] = 0x00000000;
	bufferin[2] = 0x00000020;

	errorcode = IOS_Ioctl(dvdhandle,0x12,bufferin,8,bufferout,0x20);
	if(errorcode < 0){
		free(bufferin);
		free(bufferout);
		return errorcode;
	}
	printf("Drive Inquiry:\n");
	for(i=0;i<4;i++){
		printf("%x",bufferout[i]);
	}
	printf("\n");
	free(bufferin);
	free(bufferout);
	return 1;
}

/*---------------------------------------------------------------------------*
    Name:               dvd_Inquiry
    Description:        Reset Drive
*---------------------------------------------------------------------------*/
s32 dvd_readid()
{
	s32 errorcode;

	if(!dvdopen){
		return -1;
	}

	bufferin[0] = READ_ID<<24;
	errorcode = IOS_Ioctl(dvdhandle,READ_ID,bufferin,0x20,bufferout,0x20);
	if(errorcode < 0){
		return errorcode;
	}

	return 1;
}

/*---------------------------------------------------------------------------*
    Name:               dvd_readunc()
    Description:        Reset Drive
*---------------------------------------------------------------------------*/
s32 dvd_readunc(void *buffer,u32 len, s64 offset)
{
	s32 errorcode;

	if(!dvdopen){
		return -1;
	}
	
	bufferin[0] = READ_UNC<<24;
	bufferin[1] = len;
	bufferin[2] = offset;

	errorcode = IOS_Ioctl(dvdhandle,READ_UNC,bufferin,0x20,buffer,len);
	if(errorcode < 0){
		return errorcode;
	}

	return 1;
}

/*---------------------------------------------------------------------------*
    Name:               dochecksum
    Description:        Calculates SUM of a buffer
*---------------------------------------------------------------------------*/
/*
static u32 __dochecksum (u8 *packetbuffer, int length)
{
 
int temp = 0;
int i;

	for (i = 0; i < length; i++){ 
		temp += packetbuffer[i];
	}
	return temp;
}


void writelongbe(u8 *data, u32 value)
{
	data[0] = value >> 24;
	data[1] = value >> 16;
	data[2] = value >> 8;
	data[3] = value;
}
*/

void wiidvd_stop()
{
	s32 ret = 0;
	
	dvddone = 0;
	bwDVD_LowStopMotor(0,0,__dvd_readidcb);
	while(ret>=0 && dvddone==0);
}


